package hhq.demo.fsexplore;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONArray;
import hhq.demo.wechart.popj.ChartUser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import hhq.demo.config.Conf;
import hhq.demo.config.NonStaticResourceReqHandler;
import hhq.demo.utils.FileUtil;
import hhq.demo.utils.ResJson;


/**
 * @brief 文件系统浏览器相关的Web接口，
 * 网站是 http://127.0.0.1:9966/huohuaqi/explorer/ls
 */
@RestController
@RequestMapping("/explorer")
public class FsExpController {
    
    @Autowired
    Conf config;

    private boolean check_path(String path){
        if(path.contains("../")){
            return false;
        }
        return true;
    }

    // get now path str
    private String getNowPath(String path, HttpServletRequest req){
        ChartUser user = (ChartUser)req.getSession().getAttribute("user");
        File base_dir = new File(config.ExplorerPath, user.getUid() );
        if( ! base_dir.exists() ){
            boolean ok = base_dir.mkdir();
            if(!ok)
                return "";
        }
        File now_file = new File(base_dir, path);
        return now_file.getAbsolutePath();
    }

    // 获取当前文件列表
    @RequestMapping( "/ls")
    public String ls(HttpServletRequest req, @RequestParam("path") String path ) {
        if(!check_path(path)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        File nextPath = new File(getNowPath(path, req));
        System.out.println("ls " + nextPath.getAbsolutePath());
        
        if( nextPath.exists() && nextPath.isDirectory() ){
            String[] names = FSUtil.ls(nextPath.getAbsolutePath());
            List<FileEntity> files = new ArrayList<>();
            List<FileEntity> dirs = new ArrayList<>();
            for(String name: names){
                File tmp = new File(nextPath, name);
                if( tmp.isDirectory() ){
                    FileEntity f = new FileEntity(name, true, tmp.lastModified());
                    dirs.add(f);
                }else{
                    FileEntity f = new FileEntity(name, false, tmp.lastModified());
                    files.add(f);
                }
            }
            JSONArray jarr = new JSONArray();
            for(FileEntity f: dirs){
                jarr.add(f.toJsonObject());
            }
            for(FileEntity f: files){
                jarr.add(f.toJsonObject());
            }
            return ResJson.getString(20, "succ", jarr);
        }else{
            return ResJson.getString(40, "文件夹不存在或者不是文件夹");
        }
    }
    @RequestMapping(value = "/upload", method = RequestMethod.POST,consumes = "multipart/form-data")
    public String insertFile(HttpServletRequest request
            , @RequestParam("upload") MultipartFile file
            , @RequestParam("path") String path
    )
    throws IllegalStateException, IOException 
    {
        System.out.println("path:" + path);
        System.out.println("file:" + file.getOriginalFilename() );
        if(!check_path(path)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        // int x=1;
        // if(x == 1){
        //     return ResJson.getString(20, "上传成功");
        // }
        // 如果文件不为空，写入上传路径，进行文件上传
        if (!file.isEmpty()) { 
            path = getNowPath(path, request);
            // 获取上传的文件名称，并结合存放路径，构建新的文件名称
            String filename = file.getOriginalFilename();
            //清理非法名称 < > / \ | : " * ?
            filename = FileUtil.clearNotGood(filename);
            File filepath = new File(path, filename);

            // 判断路径是否存在，不存在则新创建一个
            if (!filepath.getParentFile().exists()) {
                filepath.getParentFile().mkdirs();
            }

            // 将上传文件保存到目标文件目录
            file.transferTo(new File(path + File.separator + filename));

            return ResJson.getString(20, "上传成功");
        } else {
            return ResJson.getString(40, "上传失败");
        }
    }
    
    @RequestMapping("/rm")
    public String removeFile(
            HttpServletRequest req,
            @RequestParam("path") String path ,
            @RequestParam("name") String name    
    ){
        if(!check_path(path)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        path = getNowPath(path, req);
        if( path.length() < 10 )
            return ResJson.getString(40, "fail");
        File delFile = new File(path, name);
        System.out.println(delFile.getAbsolutePath());

        deleteLoop(delFile);

        return ResJson.getString(20, "succ");
    }
    private void deleteLoop(File f){
        if(f.isFile()){
            while(f.exists()) f.delete();
        }else{
            String[] sons = f.list();
            for(int i=0; i<sons.length; i++){
                File s = new File(f, sons[i]);
                deleteLoop(s);
            }
            f.delete();
        }
    }


    @RequestMapping(value = "/down", method = RequestMethod.GET)
    public void downloadFile(
            HttpServletRequest req,
            HttpServletResponse response
            , @RequestParam("path") String path
            , @RequestParam("name") String name) 
    {
        if(!check_path(path)){
            return;
        }
        path = getNowPath(path, req);
        File myFile = new File(path, name);
        System.out.println("downloadFile:" + myFile.getAbsolutePath());
        if ( myFile.exists() && myFile.isFile() ){ // if file exist
            OutputStream out=null;
            FileInputStream fis=null;
            try {
                // response.setContentType("application/octet-stream");
                response.setContentType("application/force-download");
                response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "No-cache");
                response.setDateHeader("Expires", 0);
                response.setHeader("Content-Disposition", "attachment;fileName="
                     + URLEncoder.encode(myFile.getName(),"UTF-8") ); // insure Chinese correct
                  out = response.getOutputStream();
                  fis=new FileInputStream( myFile );
                int len = fis.available();
                response.setIntHeader("Content-Length", len); //file size
                byte[] b = new byte[len];
                fis.read(b);
                out.write(b);
                out.flush();
            } catch (Exception e) {
                System.out.println(e.toString());
            }finally{
                try {
                    fis.close(); out.close();
                } catch (Exception e) {
                    System.out.println(e.toString());
                }
            }
    
        }else{
            try {
                response.setContentType("application/json; charset=utf-8");
                OutputStream out = response.getOutputStream();
                String mess = ResJson.getString(40, "文件不存在");
                byte[] b = mess.getBytes("UTF-8");
                out.write(b);
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    }

    
    /**
     * 视频播放 这样老方法 废弃了
     */
    @Deprecated
    @RequestMapping(value = "/video1", method = RequestMethod.GET)
    public void video_player1(
            HttpServletRequest req,
            HttpServletResponse response
            , @RequestParam("path") String path
            , @RequestParam("name") String name)
    {
        if(!check_path(path)){
            return;
        }
        path = getNowPath(path, req);
        File myFile = new File(path, name);
        System.out.println("video play File:" + myFile.getAbsolutePath());
        if ( myFile.exists() && myFile.isFile() ){  // if file exist
            OutputStream out=null;
            FileInputStream fis=null;
            try {
                response.setContentType("video/mp4");  
                response.setHeader("Accept-Ranges", "bytes");
                response.setHeader("Content-Disposition", "attachment;fileName="
                     + URLEncoder.encode(myFile.getName(),"UTF-8") ); // insure Chinese correct
                
                out = response.getOutputStream();
                fis=new FileInputStream( myFile );
                int len = fis.available();
                response.setIntHeader("Content-Length", len); //file size
                response.setIntHeader("Content-Range", len-1);
                byte[] b = new byte[len];
                fis.read(b);
                out.write(b);
                out.flush();
            } catch (Exception e) {
                System.out.println(e.toString());
            }finally{
                try {
                    fis.close(); out.close();
                } catch (Exception e) {
                    System.out.println(e.toString());
                }
            }
    
        }else{
            try {
                response.setContentType("application/json; charset=utf-8");
                response.setStatus(403);
                OutputStream out = response.getOutputStream();
                String mess = ResJson.getString(40, "文件不存在或者不是视频");
                byte[] b = mess.getBytes("UTF-8");
                out.write(b);
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } 
    } 

    @Autowired
    private NonStaticResourceReqHandler nsrrh; // 静态资源自动分段器
    /**
     * 视频播放 2
     */
    @RequestMapping(value = "/video", method = RequestMethod.GET)
    public void video_player2(
            HttpServletRequest req,
            HttpServletResponse response
            , @RequestParam("path") String path
            , @RequestParam("name") String name  )
    {
        if(!check_path(path)){
            return;
        }
        path = getNowPath(path, req);
        File myFile = new File(path, name);
        System.out.println("video play File:" + myFile.getAbsolutePath());
        if ( myFile.exists() && myFile.isFile() ){  // if file exist
            req.setAttribute(NonStaticResourceReqHandler.ATTR_FILE, myFile.getAbsolutePath());
            try {
                nsrrh.handleRequest(req, response);
            } catch (ServletException | IOException e) {
                // e.printStackTrace();
            }
    
        }else{
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        } 
    } 



    @RequestMapping("/rename")
    public String rename(
            HttpServletRequest req,
            @RequestParam("path") String path,
            @RequestParam("fn") String fn,
            @RequestParam("newfn") String newfn
    ) {
        if(!check_path(path) || !check_path(fn) || !check_path(newfn)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        File file=new File( getNowPath(path, req), fn );
        if( file.exists() ){
            file.renameTo(new File(getNowPath(path, req), newfn));
            return ResJson.getString(20, "succ");
        }
        return ResJson.getString(40, "fail");
    }

    // 文件移动
    @RequestMapping("/move")
    public String move_file(
            HttpServletRequest req,
            @RequestParam("path") String path,
            @RequestParam("fn") String fn,
            @RequestParam("newpath") String newpath
    ) {
        if(!check_path(path) || !check_path(fn) || !check_path(newpath)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        if(path.equals(newpath)){
            return ResJson.getString(20, "succ");
        } 
        File file=new File( getNowPath(path, req), fn );
        File newDir=new File( getNowPath(newpath, req) );
        File newfn=new File( getNowPath(newpath, req), fn );
        if( file.exists() && newDir.exists() && file.renameTo(newfn)){ 
            return ResJson.getString(20, "succ");
        }
        return ResJson.getString(40, "fail");
    }

    @RequestMapping("/newdir")
    public String newdir(
            HttpServletRequest req,
        @RequestParam("path") String path,
        @RequestParam("name") String fn 
    ) {
        if(!check_path(path) || !check_path(fn)){
            return ResJson.getString(40, "路径含有非法字符");
        }
        //清理非法名称 < > / \ | : " * ?
        fn = FileUtil.clearNotGood(fn);
        if(fn.equals(""))
            return ResJson.getString(40, "fail");
        File file=new File( getNowPath(path, req), fn );
        try{
            if( ! file.exists())
                file.mkdirs();
            return ResJson.getString(20, "succ");
        }catch(Exception e){
            return ResJson.getString(40, "fail");
        }
    }

}